home *** CD-ROM | disk | FTP | other *** search
- #include <Types.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <Sound.h>
- #include <SysEqu.h>
-
- #include "DylanTalk.h"
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- pascal void SpeakStringSounds(register DylanTalkGlobalPtr globals)
- {
- register Ptr text = globals->firstDialogString;
- Handle speechHandle;
- Boolean done = false;
- short i = 0;
- short lastWordStart = -1;
- short numWords = 0;
- short runStartOffset;
- OSErr err;
- Str255 word;
-
- if ( globals->dylanSndChannel != 0L) // check if we already have a channel
- QuietChannel(globals->dylanSndChannel);
- else
- {
- if (err = SndNewChannel(&(globals->dylanSndChannel), sampledSynth, initNoInterp, nil))
- return;
- }
-
- if (globals->wordQueue != nil)
- FreeQueue(globals);
- globals->wordQueue = (WordQueuePtr) NewPtrSysClear(1024L); // 1k = 256 handles = 256 word max
- if (MemError()) return;
-
- // now we have a channel and queue memory. We loop thru the string sending off words
- // to be played in our channel.
-
- // First, convert the string to all uppercase
-
- ConvertStringToUpperCase(text);
-
- i = 0;
- while (FindCharacterRun(text, i, &word, &runStartOffset)) {
- i += runStartOffset + word[0]; // Set up offset for next time through the loop
- speechHandle = PlayWord(globals->dylanSndChannel, word, globals->personalityFile);
- if (speechHandle != 0) {
- ((globals->wordQueue)->aWord)[numWords++] = speechHandle;
- ((globals->wordQueue)->aWord)[numWords] = nil;
- }
- }
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- pascal void KillStringSounds(register DylanTalkGlobalPtr globals)
- {
- if (globals->dylanSndChannel != 0L)
- {
- KillChannel( globals->dylanSndChannel, globals->playingControlSound );
- globals->playingControlSound = false;
- globals->dylanSndChannel = nil;
- }
-
- FreeQueue(globals);
- }
-
- void FreeQueue(register DylanTalkGlobalPtr globals)
- {
- register WordQueuePtr wordQueue = globals->wordQueue;
- Handle stringSound;
- short i;
-
- if (wordQueue != 0L) {
- for (i = 0; i < 256; ++i) {
- stringSound = (wordQueue->aWord)[i];
- if (stringSound != nil)
- ReleaseResource(stringSound);
- }
- DisposPtr((Ptr) wordQueue);
- globals->wordQueue = nil;
- }
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Handle GetSoundResourceForWord(ConstStr255Param word)
- {
- Handle soundResource;
-
- soundResource = Get1NamedResource('snd ', (ConstStr255Param) word);
- if ( soundResource == 0L)
- {
- soundResource = Get1Resource('snd ',word[1]+200-'A');
- if ( soundResource == 0L )
- {
- soundResource = Get1Resource('snd ', 0);
- }
- }
-
- return soundResource;
- }
-
- OSErr PlaySound(Handle theSound,SndChannelPtr channel )
- {
- OSErr err = noErr;
-
- if (theSound == 0L)
- err = ResError();
- else
- {
- HLock(theSound);
- AddSound(theSound, channel);
- }
-
- return err;
- }
-
- Boolean CheckForNumber(ConstStr255Param word)
- {
- Boolean hasNumber = false;
- short i;
-
- for (i=1; (i <= word[0]) && (!hasNumber); i++)
- {
- if ((word[i] <= '9') && ( word[i] >= '0'))
- {
- hasNumber = true;
- }
- }
- return hasNumber;
- }
-
- Handle PlayWord(SndChannelPtr channel, ConstStr255Param word, short refNum)
- {
- OSErr err = 0;
- Handle soundResource;
- short oldRef;
- long num;
-
- if (channel != 0L)
- {
- oldRef = CurResFile();
- UseResFile(refNum);
-
- soundResource = GetSoundResourceForWord(word);
- if (soundResource == nil) {
- if (CheckForNumber(word))
- {
- num = StringToNumber(word);
- if ( num < 10 ) num = 0;
- else if ( num < 100 ) num = 1;
- else if ( num < 1000 ) num = 2;
- else num = 3;
-
- soundResource = GetResource('snd ',226+num);
- }
- }
- err = PlaySound(soundResource, channel);
- UseResFile(oldRef);
- }
- if (err)
- return 0L;
- else
- return soundResource;
- }
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- void AddSound(Handle sndHandle,SndChannelPtr channel)
- {
- SndCommand theCmd;
- long offset;
- OSErr err;
-
- offset = GetBufferOffset(sndHandle);
- theCmd.cmd = bufferCmd;
- theCmd.param1 = 0;
- theCmd.param2 = (long) *sndHandle + offset;
-
- err = SndDoCommand(channel, &theCmd, true);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- long GetBufferOffset(Handle sndHandle)
- {
- short synths;
- short howManyCmds;
- Ptr cruisePtr;
- long sndDataOffset;
-
- sndDataOffset = 0;
- cruisePtr = *sndHandle;
- if (cruisePtr != nil) {
- if ( ((Snd1HdrPtr)cruisePtr)->format == firstSoundFormat ) {
- synths = ((Snd1HdrPtr)cruisePtr)->numSynths;
- cruisePtr += sizeof(Snd1Header) + (sizeof(SynthInfo) * synths);
- }
- else
- cruisePtr += sizeof(Snd2Header);
- howManyCmds = *((short *)cruisePtr); // pointing at number of cmds
- cruisePtr += sizeof(howManyCmds);
-
- // cruisePtr is now at the first sound command
- // cruise all commands and find a soundCmd or bufferCmd
- do {
- switch (((SndCmdPtr)cruisePtr)->cmd) {
-
- case (soundCmd | dataOffsetFlag):
- case (bufferCmd | dataOffsetFlag):
- sndDataOffset = ((SndCmdPtr)cruisePtr)->param2;
- howManyCmds = 0; // done, get out of loop
- break;
-
- default: // catch any other type of cmd
- cruisePtr += sizeof(SndCommand);
- howManyCmds -= 1;
- break;
- }
- } while (howManyCmds >= 1); // done with all the commands
- }
- return(sndDataOffset);
- }
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- void QuietChannel(SndChannelPtr channel)
- {
- OSErr err;
- SndCommand theCmd;
-
- theCmd.cmd = flushCmd;
- err = SndDoImmediate(channel, &theCmd);
- theCmd.cmd = quietCmd;
- err = SndDoImmediate(channel, &theCmd);
- }
-
- void KillChannel( SndChannelPtr channel, Boolean waitForSoundToFinish )
- {
- OSErr err;
- SCStatus status;
-
- // If we’re playing a button title, wait for the sound to finish before
- // disposing of the sound channel.
-
- if (waitForSoundToFinish) {
- do {
- err = SndChannelStatus(channel, sizeof(status), &status);
- } while ((err == noErr) && (status.scChannelBusy));
-
- }
- err = SndDisposeChannel(channel, true);
- }